package jlib.component.tool.catchers {
	import jlib.component.tool.event.SelectToolEvent;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.text.TextField;

	/**
	 * @author 박종희
	 */
	public class NomalCatcher extends EventDispatcher implements ICatcher
	{
		protected var _catchedList:Array;
		private var startPoint:Point, endPoint:Point;
		private var stage:DisplayObject;
		private var canvas:DisplayObjectContainer;
		
		private var mode:String;
		
		public function NomalCatcher(): void
		{
			_catchedList = new Array();
			startPoint = new Point(), endPoint = new Point();
		}
		
		public function initialize(): void
		{
			if(_catchedList) _catchedList.splice(0,_catchedList.length);
			_catchedList = new Array();
		}
		
		//특화 메서드 수정요망 ~ !!! 하위 객체로 행위 위임.
		public function press( e:MouseEvent ): void
		{
			startPoint.x = stage.mouseX, startPoint.y = stage.mouseY;			
			var target:DisplayObject = e.target as DisplayObject;
			setMode(_inspectState(target));
			inspect(e);
			this.dispatchEvent(new SelectToolEvent(SelectToolEvent.CHANGE_STATE, getMode()));
		}
		
		public function move( e:MouseEvent ): void { e.updateAfterEvent(); }
		public function release( e:MouseEvent ): void
		{
			endPoint.x = stage.mouseX, endPoint.y = stage.mouseY;
			if( mode == CatcherState.CATCH_MULTI ) catchMultiTargets( e.shiftKey );
		}
		
		protected function _inspectState($target:DisplayObject): String 
		{
			var result:String;
			if($target == stage || $target == canvas){
				result = CatcherState.CATCH_MULTI;
			}else if(canvas.contains($target)){
				
				if(isIgnore($target)) result = CatcherState.CATCH_MULTI;
				else {
					if(isEmptyCatchList()){
						result = CatcherState.CATCH_SINGLE;
					}else {
						if(isCatched($target)){
							result = CatcherState.CATCHED_OVERLAP;
						}else {
							result = CatcherState.CATCHED_NEWSINGLE;
						}
					}
				}
			}else {
				result = CatcherState.CATCHED_ANOTHER;
			}
			return result;
		}
		
		protected function inspect( e:MouseEvent ): void
		{
			var target:DisplayObject = e.target as DisplayObject;
			
			switch(getMode()){
				case CatcherState.CATCHED_IGNORE :
					// this.dispatchEvent(new SelectToolEvent(SelectToolEvent.LOCK_OBJECT_SELECT));
				break;
				case CatcherState.CATCH_SINGLE :
					catchSingleTarget(target);
				break;
				case CatcherState.CATCHED_OVERLAP:
					if( e.shiftKey ) removeTarget(target);
					else setMode(CatcherState.CATCHED_OVERLAP);
				break;
				case CatcherState.CATCHED_NEWSINGLE :
					if( e.shiftKey ) appendTarget(target);
					else catchSingleTarget(target);
				break;
			}
		}
		
		private function catchSingleTarget( target:DisplayObject ): void
		{
			if(isIgnore(target)) return;
			_catchedList = [ target ];
			this.dispatchEvent(new SelectToolEvent(SelectToolEvent.CHANGE_SELECTLIST, _catchedList));
		}
		
		private function appendTarget( target:DisplayObject ): void
		{
			if(isIgnore(target)) return;
			_catchedList.push( target );
			this.dispatchEvent(new SelectToolEvent(SelectToolEvent.CHANGE_SELECTLIST, _catchedList));
		}
		
		private function removeTarget( target:DisplayObject ): void
		{
			if(isIgnore(target)) return;
			var index:int = _catchedList.indexOf(target);
			_catchedList.splice(index,1);
			this.dispatchEvent(new SelectToolEvent(SelectToolEvent.CHANGE_SELECTLIST, _catchedList));
		}
		
		// Rectangle API 를 이용한 
		private function catchMultiTargets( isPressShift:Boolean ): void
		{
			var cindex:int, tindex:int;
			var targetsArray:Array = new Array();
			var areaRect:Rectangle = getRect( startPoint, endPoint );
			
			for( var i:int=0;i<canvas.numChildren;i++){
				if( areaRect.intersects(canvas.getChildAt(i).getBounds(stage))){
					if(isIgnore(canvas.getChildAt(i))) continue;
					targetsArray.push(canvas.getChildAt(i));
				}
			}
			if( isPressShift ){
				for each( var target:* in targetsArray ){
					cindex = _catchedList.indexOf(target);
					tindex = targetsArray.indexOf(target);
					if( cindex > -1) _catchedList.splice(cindex,1);
					else _catchedList.push( target );
				}
			}else _catchedList = targetsArray;
			if( _catchedList.length > 0 ) this.dispatchEvent(new SelectToolEvent(SelectToolEvent.CHANGE_SELECTLIST, _catchedList));
		}
		
		// 그리는 함수 
		private function getRect( startPoint:Point, endPoint:Point ): Rectangle
		{
			var sizePoint:Point = new Point((endPoint.x-startPoint.x), (endPoint.y-startPoint.y));
			if(sizePoint.x < 0) startPoint.x = endPoint.x; 
			if(sizePoint.y < 0) startPoint.y = endPoint.y;
			return new Rectangle( startPoint.x, startPoint.y, Math.abs(sizePoint.x), Math.abs(sizePoint.y) );
		}
		
		public function setStage( value:DisplayObject ): void { this.stage = value; /* drawPanel*/  }
		public function setCanvas( value:DisplayObjectContainer ): void { this.canvas = value; }
		
		public function getMode(): String { return mode; }
		public function setMode($mode:String): void  { this.mode = $mode; }
		
		public function setCatchedList($list:Array): void { _catchedList = $list; }
		public function getCatchedList(): Array { return _catchedList; }
		
		public function reset():void
		{
			this._catchedList = new Array();
			this.dispatchEvent(new SelectToolEvent(SelectToolEvent.CHANGE_SELECTLIST, _catchedList));
		}
		
		public function isCatched( target:DisplayObject ): Boolean { return ( _catchedList.indexOf(target) > -1 ); }
		public function isEmptyCatchList(): Boolean { return ( _catchedList == null || _catchedList.length == 0 );	}
		
		protected function isIgnore($target:Object): Boolean
		{
			return ($target.hasOwnProperty("lock") && $target["lock"])||($target.hasOwnProperty("isBackground") && $target["isBackground"]);
		}
		
		
	}//c
}//p
